﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

//
//Note: You need to change the paths to get at the name data files.
//TODO: Make these paths relative and move data files.

namespace LinqToXml
{
	class Program
	{

		public static string[] FNames;
		public static string[] MNames;
		public static string[] LNames;

		static void Main(string[] args)
		{

			//Number of people to create
			int nRelationshipLowerBound = 5;
			int nRelationshipUpperBound = 10;
			int numPeopl = 200;
			int ind;

			//for storing name data
			FNames = new string[1000];
			MNames = new string[1000];
			LNames = new string[1000];

			Dictionary<string, string> dictRels = new Dictionary<string, string>();
			//shortcuts for xml tag names
			const string f = "firstname";
			const string l = "lastname";
			const string g = "gender";
			const string r = "relationships";
			const string d = "id";
			const string ppl = "people";

			string strFirst;
			string strLast;
			string strSex;
			string strID;

			//used for random access by id
			Dictionary<string, string> dictNames = new Dictionary<string, string>();

			XElement root = new XElement(ppl);
			XElement person;
			XElement fname;
			XElement lname;
			XElement id;
			XElement sex;
			XElement relationships;

			XDocument doc =
			new XDocument(
				new XDeclaration("1.0", "utf-8", "yes"),
				new XComment("XML Data")
				);

			ReadData();
			
			//Create Person Data
			Random rand = new Random(DateTime.Now.Millisecond);

			for (int i = 0; i < numPeopl; i++)
			{
				//alternate creating men and women
				strLast = LNames[rand.Next(0, 999)];
				if (i % 2 == 0)
				{
					strSex = "M";
					strFirst = MNames[rand.Next(0, 889)];
				}
				else
				{
					strSex = "F";
					strFirst = FNames[rand.Next(0, 889)];
				}
				//create id by concat first and last name, then by unique number
				ind = 0;
				strID = strFirst + strLast + ind.ToString();
				while (dictNames.ContainsKey(strID) == true)
				{
					ind++;
					strID = strFirst + strLast + ind.ToString();
				}

				//add id to dictionary and to indexed array
				dictNames[strID] = strID ;
				
				fname = new XElement(f, strFirst);
				lname = new XElement(l, strLast);
				sex = new XElement(g, strSex);
				id = new XElement(d, strID);
				relationships = new XElement(r);

				//create person element
				person = new XElement("person",
					fname,
					lname,
					id,
					sex
					);
				root.Add(person);
			}

			string strOtherId;
			string strType;
			int otherInd;
			bool skipRelationship = false;
			XElement other;

			int j = 0;
			//Set relationships for each person in list
			foreach (XElement p in root.Elements())
			{
				relationships = new XElement(r);

				//get id of element
				strID = (string)p.Element("id");

				//choose random number of relationships
				ind = rand.Next(nRelationshipLowerBound,nRelationshipUpperBound);

				dictRels.Clear();
				for (int i = 0; i < ind; i++)
				{
					skipRelationship = false;
					//pick random person from list
					otherInd = rand.Next(0,numPeopl);

					
					//select person element based on pick
					other = root.Elements().ElementAt(otherInd);

					//check whether this person has relationships already added
					if (otherInd < j)
					{
						XElement otherRels = other.Element("relationships");
						foreach (XElement orel in otherRels.Elements("person"))
						{
							if ((string)orel.Element("id") == strID)
							{
								//name is already there.
								skipRelationship = true;
							}
						}
					}

					if (skipRelationship)
						continue;

					strOtherId = (string)other.Element("id");

					//if we selected the same person, skip and go on.
					if (strID == strOtherId)
						continue;

					if (dictRels.ContainsKey(strOtherId))
						continue;
					dictRels.Add(strOtherId, strOtherId);
					if ((string)other.Element(g) == (string)p.Element(g))
						strType = "friend";
					else
						strType = "lovers";
					relationships.Add(new XElement("person",
						new XElement("id",strOtherId),
						new XElement("type",strType)
						)
					);
				}
				j++;
				p.Add(relationships);
			}
		
			doc.Add(root);
			doc.Save(@"C:\test.xml");
			
				
		}

		public static void Debug(string[] FNames, string[] MNames, string[] LNames)
		{
			for (int i = 0; i < FNames.Length; i++)
			{
				Console.WriteLine("f:" + FNames[i]);
				Console.WriteLine("m:" + MNames[i]);
				Console.WriteLine("l:" + LNames[i]);
			}
		}

		public static void ReadData()
		{
			string line;
			int ind = 0;

			//ReadData
			StreamReader reader = new StreamReader(@"C:\Working\Graphos\Members\cobb\NameData\female.csv");
			try
			{
				while (!reader.EndOfStream)
				{
					line = reader.ReadLine();
					if (ind < FNames.Length)
						FNames[ind] = line;
					else break;
					ind++;
				}

			}
			catch { Console.Write("No Data"); }
			finally
			{
				reader.Close();
			}

			ind = 0;
			reader = new StreamReader(@"C:\Working\Graphos\Members\cobb\NameData\male.csv");

			try
			{
				while (!reader.EndOfStream)
				{
					line = reader.ReadLine();
					if (ind < FNames.Length)
						MNames[ind] = line;
					else break;
					ind++;
				}
			}
			catch { Console.Write("No Data"); }
			finally { reader.Close(); }


			ind = 0;
			reader = new StreamReader(@"C:\Working\Graphos\Members\cobb\NameData\last.csv");

			try
			{
				while (!reader.EndOfStream)
				{
					line = reader.ReadLine();
					if (ind < FNames.Length)
						LNames[ind] = line;
					else break;
					ind++;
				}
			}
			catch { Console.WriteLine("No Data"); }
			finally { reader.Close(); }
		}


	}
}

